"""
Case Type   : 系统内部使用工具
Case Name   : gs_ctl notify指定cascade_standby模式启动备机
Create At   : 2022/06/08
Owner       : opentestcase012
Description :
    1.停止备2并以pending模式启动并进行查询
    2.备2执行级联备并进行再次查询
    3.清理环境
Expect      :
    1.pending模式启动成功
    2.执行备2级联备成功
    3.清理成功
History     :
    Modified by opentestcase034 2023/2/13: 优化用例准确断言及正确定义变量
"""
import os
import time
import unittest

from yat.test import Node
from yat.test import macro

from testcase.utils.Common import Common
from testcase.utils.Common import CommonSH
from testcase.utils.Logger import Logger

primary_sh = CommonSH('PrimaryDbUser')


@unittest.skipIf(3 != primary_sh.get_node_num(), '非1+2环境不执行')
class Tools(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.common = Common()
        self.log.info(f'----{os.path.basename(__file__)} start----')
        self.standby2_node = Node('Standby2DbUser')
        self.comsh1 = CommonSH('Standby1DbUser')
        self.comsh2 = CommonSH('Standby2DbUser')
        self.standby1_node = Node('Standby1DbUser')

    def test_cascade_standby(self):
        text = '----step1:停止备2并以pending模式启动并进行查询 expect:成功----'
        self.log.info(text)
        status = primary_sh.get_db_cluster_status(param='detail')
        self.log.info(status)
        self.assertEqual(4, status.count('Normal'), '数据库状态异常')

        stop_res = self.comsh2.stop_db_instance()
        self.assertIn('server stopped', stop_res, '数据库停止失败')
        start_res = self.comsh2.start_db_instance(mode='pending')
        self.assertIn('server started', start_res, '数据库启动失败')
        self.query_cmd = f'source {macro.DB_ENV_PATH};' \
                    f'gs_ctl query -D {macro.DB_INSTANCE_PATH};'
        self.log.info(self.query_cmd)
        time.sleep(10)
        query_res = self.common.get_sh_result(self.standby2_node,
                                              self.query_cmd)
        self.assertIn('Pending', query_res, '数据库pending启动失败')
        self.assertIn('Need repair', query_res, '数据库pending启动失败')

        text = '----step2:备2执行级联备并进行再次查询 expect:成功----'
        self.log.info(text)
        restart_cmd = f'source {macro.DB_ENV_PATH};' \
                      f'gs_ctl restart -D {macro.DB_INSTANCE_PATH} ' \
                      f'-M cascade_standby;'
        self.log.info(restart_cmd)
        restart_res = self.common.get_sh_result(self.standby2_node, restart_cmd)
        self.assertIn('server started', restart_res, '数据库启动失败')
        time.sleep(10)
        query_res = self.common.get_sh_result(self.standby2_node,
                                              self.query_cmd)
        self.assertIn('Cascade Standby', query_res, '数据库casecade模式启动失败')
        self.assertEqual(4, query_res.count('Normal'), '数据库casecade模式启动失败')

        slot_sql = 'select slot_name from pg_get_replication_slots();'
        res = self.comsh1.execut_db_sql(slot_sql)
        self.log.info(res)
        self.assertNotIn('(0 row)', res, 'slot_name查询失败')
        self.slot_name = res.splitlines()[-2].strip()
        self.log.info(self.slot_name)

    def tearDown(self):
        text = "----step3:恢复环境 expect:成功----"
        self.log.info(text)
        restart_cmd = f'source {macro.DB_ENV_PATH};' \
                      f'gs_ctl restart -D {macro.DB_INSTANCE_PATH} -M standby;'
        self.log.info(restart_cmd)
        restart_res = self.common.get_sh_result(self.standby2_node, restart_cmd)
        time.sleep(10)
        query_res = self.common.get_sh_result(self.standby2_node,
                                              self.query_cmd)
        drop_cmd = f"SELECT * FROM " \
                   f"pg_drop_replication_slot('{self.slot_name}');"
        self.log.info(drop_cmd)
        res = self.comsh1.execut_db_sql(drop_cmd,
                                        dbname=f'{self.standby1_node.db_name}')
        self.log.info(res)
        self.assertIn('pg_drop_replication_slot', res, '逻辑复制槽删除失败')
        self.assertIn('server started', restart_res, '数据库启动失败')
        self.assertIn('Standby', query_res, '数据库恢复失败')
        self.assertEqual(4, query_res.count('Normal'), '数据库恢复失败')
        self.log.info(f'----{os.path.basename(__file__)} finish----')
